package com.sfang.common.util.http;

import com.alibaba.fastjson.JSON;
import com.sfang.common.util.string.StringUtils;
import org.apache.http.HttpResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 * Created by psalmody on 2016/12/22.
 */
public class HttpServletUtil {
    private static Logger LOGGER = LoggerFactory.getLogger(HttpServletUtil.class);

    public static void write(HttpServletResponse response, String content) {

        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            response.getWriter().write(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void write(HttpServletResponse response, Map<String, String> headers, byte[] content) {
        ServletOutputStream sos = null;
        try {
            setHeaders(response, headers);

            sos = response.getOutputStream();
            if (content != null) {
                sos.write(content);
            } else {
                sos.write("null!".getBytes());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (sos != null) {
                try {
                    sos.flush();
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void writeFile(Map<String, String> headers, HttpServletResponse response, byte[] content) {
        try (ServletOutputStream sos = response.getOutputStream()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                response.setHeader(entry.getKey(), entry.getValue());
            }
            if (content != null) {
                sos.write(content);
            } else {
                sos.write("null!".getBytes());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 允许请求机器跨域
     *
     * @param response 响应体
     */
    public static void allowCrossDomain(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
    }

    /**
     * 获取所有请求包头配置(不做cookie和length的校验)
     *
     * @param httpServletRequest 请求
     * @return 包头
     */
    public static Map<String, String> getAllHeadersNoCheck(HttpServletRequest httpServletRequest) {
        Map<String, String> headers = new HashMap<String, String>();
        Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            String header = httpServletRequest.getHeader(name);

            //清除cookie和content-length
            if ("cookie".equals(name)) {
                continue;
            } else if ("content-length".equals(name)) {
                continue;
            }

            headers.put(name, header);
        }

        return headers;
    }

    /**
     * 获取所有请求包头配置
     *
     * @param httpServletRequest 请求
     * @return 包头
     */
    public static Map<String, String> getAllHeaders(HttpServletRequest httpServletRequest) {
        Map<String, String> headers = new HashMap<String, String>();
        Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            String header = httpServletRequest.getHeader(name);

            headers.put(name, header);
        }

        return headers;
    }


    /**
     * 设置包头配置
     *
     * @param httpServletResponse 响应体
     * @param headers             包头
     */
    public static void setHeaders(HttpServletResponse httpServletResponse, Map<String, String> headers) {
        if (httpServletResponse == null || headers == null)
            return;
        Iterator<Map.Entry<String, String>> iterator = headers.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            String name = entry.getKey();
            String value = entry.getValue();

            //此处只设置ContentType
            if ("ContentType".equals(name))
                httpServletResponse.setHeader(name, value);
        }
    }

    /**
     * 读取响应字节流
     *
     * @param httpResponse 响应体
     * @return 字节流
     */
    public static byte[] getResponseContent(HttpResponse httpResponse) {
        byte[] in_b = null;
        if (httpResponse != null) {
            InputStream inputStream = null;
            ByteArrayOutputStream swapStream = null;
            try {
                inputStream = httpResponse.getEntity().getContent();
                swapStream = new ByteArrayOutputStream();

                //buff用于存放循环读取的临时数据
                byte[] buff = new byte[1024];
                int rc = 0;
                while ((rc = inputStream.read(buff, 0, 1024)) > 0) {
                    swapStream.write(buff, 0, rc);
                }

                //in_b为转换之后的结果
                in_b = swapStream.toByteArray();

            } catch (IOException e) {
                e.printStackTrace();
                return in_b;
            } finally {
                if (inputStream != null)
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                if (swapStream != null)
                    try {
                        swapStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
        }
        return in_b;
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        ip = request.getHeader("X-Forwarded-For");
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值，第一个为真实IP。
            int index = ip.indexOf(',');
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        } else {
            return request.getRemoteAddr();
        }
    }

    public static Map assemblyHeaders(HttpServletRequest request) {
        Map<String, String> map = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }

        return map;
    }

    public static String getIpV6Addr(HttpServletRequest request) {

        Map map = assemblyHeaders(request);
        LOGGER.warn(String.format("getIpV6Addr headers:%s", JSON.toJSONString(map)));

        String ip = request.getHeader("CF-Connecting-IP");

        if (StringUtils.isEmpty(ip) && StringUtils.isNotEmpty(request.getHeader("X-Forwarded-For"))) {

            if (StringUtils.isEmpty(ip)) {

                String ccip = request.getHeader("CC-Forwarded-For");

                if (StringUtils.isNotEmpty(ccip)) {
                    //当蓝汛IP不为空时取蓝汛IP
                    ip = ccip.trim();
                }else{
                    ccip = request.getHeader("CDN-SRC-IP");
                    if (StringUtils.isNotEmpty(ccip)) {
                        //当网宿IP不为空时取网宿IP
                        ip = ccip.trim();
                    }
                }

                if (StringUtils.isEmpty(ip)) {
                    String arrIps = request.getHeader("ARR_IP");
                    String arrip = "";
                    if (StringUtils.isNotEmpty(arrIps)) {
                        arrip = arrIps.split(":")[0].trim();
                    }
                    String haip = "";
                    if (StringUtils.isNotEmpty(request.getHeader("HA_IP"))) {
                        //是HA且非ARR时  获取HTTP_HA_IP作为真实IP
                        haip = request.getHeader("HA_IP");
                    }

                    if (StringUtils.isNotEmpty(arrip) && org.apache.commons.lang3.StringUtils.isEmpty(haip)) {
                        ip = arrip;
                    } else if (StringUtils.isEmpty(arrip) && StringUtils.isNotEmpty(haip)) {
                        //是ARR且非HA时  获取HTTP_ARR_IP作为真实IP
                        ip = haip;
                    } else if (StringUtils.isNotEmpty(arrip) && StringUtils.isNotEmpty(haip)) {
                        //是ARR且是HA时  获取HTTP_X_FORWARDED_FOR  倒数第二个IP
                        String[] split = request.getHeader("X-Forwarded-For").split(",");
                        if (split.length > 2) {
                            ip = split[split.length - 2];
                        }
                    }
                }

                if (StringUtils.isEmpty(ip)) {
                    ip = request.getRemoteAddr();
                }
            }
        } else if (StringUtils.isEmpty(ip)) {
            ip = getIpAddr(request);
        }

        LOGGER.warn(String.format("getIpV6Addr headers:%s ip:%s", JSON.toJSONString(map), ip));
        return ip;
    }

}
